package com.youtills.resource;

import java.util.HashMap;
import java.util.HashSet;

/**
 * TODO - !!!doc me!!!
 *
 * @author ravi.chiluveru
 * @since 1.0 (3/6/15)
 */
public final class ResourceType<T extends Resource> {

    private static final Manager manager = new Manager();

    private final Class<T> resourceClass;
    private final long resourceType;
    /*
    TODO figure out sub/super types.
     */
    private final HashSet<ResourceType>superTypes;
    private final HashSet<ResourceType>subTypes;

    public ResourceType(final Class<T> resourceClass, final long resourceType) {
        this.resourceClass = resourceClass;
        this.resourceType = resourceType;
        this.superTypes = new HashSet<>();
        this.subTypes = new HashSet<>();
    }

    public long getResourceType() {
        return this.resourceType;
    }

    public Class<T> getResourceClass() {
        return this.resourceClass;
    }

    public static <T extends Resource> ResourceType registerResourceType(Class<T> resourceClass) {
            return manager.registerResourceType(resourceClass);
    }

    public static ResourceType getResourceType(long resourceType) {
        return manager.getResourceType(resourceType);
    }
    public static <T extends Resource> ResourceType getResourceType(Class<T> resourceClass) {
            return manager.getResourceType(resourceClass);
    }

    private static class Manager<T extends Resource> {
        final HashMap<Class<T>, ResourceType> resourceTypes;
        final HashMap<Long, ResourceType> resourceTypesById;
        private Manager() {
            resourceTypes = new HashMap<>();
            resourceTypesById = new HashMap<>();
        }

        synchronized ResourceType<T> registerResourceType(Class<T> resourceClass) {
            ResourceType<T> type = getResourceType(resourceClass);
            if(type != null) {
                throw new RuntimeException("Resource Type already registered");
            } else {
                long typeId = type(resourceClass.getName());
                if (typeId < 1) {
                    throw new RuntimeException("unable to get/find resource type id");
                }
                type = new ResourceType<T>(resourceClass, typeId);
                resourceTypes.put(resourceClass, type);
                resourceTypesById.put(typeId, type);
                return type;
            }

        }

        ResourceType getResourceType(long type) {
            return resourceTypesById.get(type);
        }
        ResourceType<T> getResourceType(Class<T> resourceClass) {
            return resourceTypes.get(resourceClass);
        }

        private long type(String className) {
            //TODO - get it from persisted
            if("com.youtills.domain.contact.Address".equals(className)) {
                return 101;
            } else if("com.goodedeeds.domain.resource.School".equals(className)) {
                return 100001;
            } else if("com.goodedeeds.domain.resource.Project".equals(className)) {
                return 100002;
            } else if("com.goodedeeds.domain.resource.Vendor".equals(className)) {
                return 100003;
            }
            return -1;
        }
    }
}
